import { useEffect, useRef } from 'react';
import { useSafeState, useMemoizedFn, useUpdateEffect, useUnmount } from 'ahooks';
import { SubHistory } from './types';
import { createNewText } from './helper';


export const useMessages = (defaultMessages: SubHistory[] = []) => {
  const [messages, setMessages] = useSafeState<SubHistory[]>(defaultMessages);

  const getLaster = useMemoizedFn(() => {
    return messages[messages.length - 1];
  });

  // 插入文字
  const insertText = useMemoizedFn((text: string) => {
    const isEmpty = !messages.length;

    // 最新的一行不为文本类型
    if (getLaster()?.type !== 'text') {
      messages.push(createNewText(isEmpty));
    }

    const laster = getLaster();
    laster.text += text;

    setMessages([...messages]);
  });

  /**
   * 开始打印下一行
   * @param index 打印完成的当前行
   * */
  const prinitNext = (index: number) => {
    const nextIndex = index + 1;
    const current = messages[index];
    const next = messages[nextIndex];

    current.prinit = false;
    current.prinitEnd = true;

    if (next) next.visible = true;
    setMessages([...messages]);
  }

  // 任务完成
  const taskCompelete = useMemoizedFn(() => {
    const laster = getLaster();
    laster.isBreak = true;
    laster.prinitEnd = true;
    setMessages([...messages]);
  });

  return {
    messages,
    insertText,
    prinitNext,
    taskCompelete
  };
}


type UsePrintTextParams = {
  text: string;
  isBreak?: boolean;
  prinit: boolean;
  prinitEnd: boolean;
  onPrintEnd?: () => void;
  onPrinit?: () => void;
}

export const usePrintText = (params: UsePrintTextParams) => {
  const {
    text,
    prinit,
    isBreak,
    prinitEnd,
    onPrinit,
    onPrintEnd
  } = params;

  const cursorRef = useRef(0);
  const runRef = useRef(false);
  const timer = useRef<NodeJS.Timeout>();

  const [loading, setLoading] = useSafeState(prinit);
  let [_text, setText] = useSafeState(prinit ? '' : text);

  const onPrintCompelete = useMemoizedFn(() => {
    if (runRef.current) return;
    setLoading(false);
    onPrintEnd?.();
  });

  const printTask = useMemoizedFn(() => {
    const cursor = cursorRef.current;
    const letter = text?.[cursor] || '';
    cursorRef.current += 1;

    _text += letter;
    setText(_text);

    if (_text === text) {
      runRef.current = false;
      if (isBreak) onPrintCompelete();
    } else {
      timer.current = setTimeout(printTask, 20);
    }
    onPrinit?.();
  });

  const runTask = useMemoizedFn(() => {
    runRef.current = true;
    clearTimeout(timer.current);
    cursorRef.current = _text.length;
    printTask();
  });

  const onStart = useMemoizedFn(() => {
    // 不需要打印效果
    if (!prinit) return;
    if (!runRef.current) runTask();
  });

  useEffect(onStart, [text]);
  useUnmount(() => clearTimeout(timer.current));
  useUpdateEffect(onPrintCompelete, [prinitEnd]);

  return [_text, loading] as [string, boolean];
}